package com.example.librarymanagementsystembackend.borrowingmanagement.service;

import com.example.librarymanagementsystembackend.bookmanagement.entity.BookInformation;
import com.example.librarymanagementsystembackend.bookmanagement.service.BookService;
import com.example.librarymanagementsystembackend.borrowingmanagement.annotation.LoadSystemSettings;
import com.example.librarymanagementsystembackend.borrowingmanagement.entity.BorrowBooksDTO;
import com.example.librarymanagementsystembackend.borrowingmanagement.entity.BorrowRecord;
import com.example.librarymanagementsystembackend.borrowingmanagement.mapper.BorrowingRecordMapper;
import com.example.librarymanagementsystembackend.systemicfunctions.entity.SystemSettingsEntity;
import com.example.librarymanagementsystembackend.systemicfunctions.service.SystemService;
import com.example.librarymanagementsystembackend.usermanagement.annotation.LogUserAction;
import com.example.librarymanagementsystembackend.usermanagement.entity.UserAction;
import com.example.librarymanagementsystembackend.usermanagement.service.UserActionService;
import com.example.librarymanagementsystembackend.utils.InvalidRequestException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class BorrowingRecordService {

    @Autowired
    private BorrowingRecordMapper borrowingRecordMapper;

    @Autowired
    private BookService bookService;

    @Autowired
    private SystemService systemService;

    @Autowired
    private UserActionService userActionService;

    private int maxBorrowLimit;
    private int borrowPeriodDays;
    private BigDecimal dailyOverdueFine;

    // 在服务初始化时加载一次设置。
    @PostConstruct
    public void init() {
        updateSettingsFromSystemService();
    }

    /**
     * 每次加载方法的时候, 查询系统配置
     */
    public void updateSettingsFromSystemService() {
        SystemSettingsEntity settings = systemService.getSystemSettings();
        this.maxBorrowLimit = settings.getBorrowLimit();
        this.borrowPeriodDays = settings.getBorrowPeriod();
        this.dailyOverdueFine = settings.getDailyOverdueFine();
    }

    /**
     * 借书服务
     *
     * @param borrowBooksDTO 借书信息
     * @return 借阅记录ID
     */
//    @LogUserAction
    @LoadSystemSettings  // 更新设置
    @Transactional
    public Integer borrowBook(BorrowBooksDTO borrowBooksDTO) {
        UserAction userAction = new UserAction(); // 用户日志

        try {
            Integer userId = borrowBooksDTO.getUserId();        // 获取借阅 用户ID
            Integer bookId = borrowBooksDTO.getBookId();        // 获取借阅 书本ID
            String borrowTime = borrowBooksDTO.getBorrowTime(); // 获取借阅时间

            userAction.setUserId(userId); // 记录UserID

            // 1. 检查用户借书资格
            validateBorrowingEligibility(userId);

            // 获取图书信息
            BookInformation bookObj = bookService.getBookById(bookId);

            int bookStock = bookObj.getStock(); // 获取库存

            // 2. 检查图书库存
            if (!(bookStock > 0)) {
                throw new InvalidRequestException("图书库存不足，无法借阅");
            }

            // 3. 创建借阅记录
            BorrowRecord borrowRecord = new BorrowRecord();
            borrowRecord.setUserId(userId);
            borrowRecord.setBookId(bookId);
            borrowRecord.setBorrowTime(borrowTime);
            borrowRecord.setReturnTime(null); // 未归还
            borrowRecord.setOverdueDays(0);
            borrowRecord.setOverdueFine(BigDecimal.ZERO); // 0 没有逾期

            borrowingRecordMapper.addBorrowingRecordByUserId(borrowBooksDTO);  // 添加借阅记录

            // 4. 更新图书库存
            --bookStock; // 该图书库存 -1
            bookObj.setStock(bookStock);
            bookService.updateBook(bookObj);

            // 添加记录 借书成功
            userAction.setActionTime(LocalDateTime.now()); // 记录时间
            userAction.setActionContent("借书成功");

            return borrowRecord.getBookId(); // BorrowRecord ID字段
        } catch (InvalidRequestException e) {
            userAction.setActionTime(LocalDateTime.now());
            userAction.setActionContent(e.getMessage());
            throw e;
        } finally {
            try {
                userActionService.createUserAction(userAction); // 即使主事务回滚，也能提交日志
            } catch (Exception ex) {
                // 日志失败可选处理（如打印警告）
                System.err.println("用户行为日志记录失败: " + ex.getMessage());
            }
        }
    }



    /**
     * 还书 通过借阅ID 和 还书时间
     */
    @LoadSystemSettings // 更新设置
    @Transactional
    public BigDecimal returnBook(Integer borrowId, String returnTime) {
        UserAction userAction = new UserAction(); // 用户日志
        userAction.setUserId(getUserIdFromBorrowRecord(borrowId)); // 获取用户ID（自定义方法）

        try {
            // 1. 根据借阅ID获取借阅记录
            BorrowRecord borrowRecord = borrowingRecordMapper.getBorrowRecordById(borrowId);

            // 2. 验证记录有效性
            if (borrowRecord == null) {
                throw new InvalidRequestException("借阅记录不存在");
            }
            if (borrowRecord.getReturnTime() != null) {
                throw new InvalidRequestException("该图书已归还");
            }

            // 3. 解析日期时间
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime borrowDateTime = LocalDateTime.parse(borrowRecord.getBorrowTime(), formatter);
            LocalDateTime returnDateTime = LocalDateTime.parse(returnTime, formatter);

            // 4. 计算逾期情况
            LocalDateTime dueDateTime = borrowDateTime.plusDays(borrowPeriodDays);
            int overdueDays = 0;
            BigDecimal overdueFine = BigDecimal.ZERO;

            if (returnDateTime.isAfter(dueDateTime)) {
                overdueDays = (int) ChronoUnit.DAYS.between(dueDateTime, returnDateTime);
                overdueFine = dailyOverdueFine.multiply(BigDecimal.valueOf(overdueDays));
            }

            // 5. 更新借阅记录
            borrowRecord.setReturnTime(returnTime);
            borrowRecord.setOverdueDays(overdueDays);
            borrowRecord.setOverdueFine(overdueFine);
            borrowingRecordMapper.updateBorrowRecord(borrowRecord);

            // 6. 更新图书库存
            BookInformation book = bookService.getBookById(borrowRecord.getBookId());
            book.setStock(book.getStock() + 1);
            bookService.updateBook(book);

            // 设置日志内容
            userAction.setActionTime(LocalDateTime.now());
            userAction.setActionContent("还书成功，借阅ID：" + borrowId + "，逾期天数：" + overdueDays + "，罚款金额：" + overdueFine);

            return overdueFine;

        } catch (InvalidRequestException e) {
            // 异常情况下设置日志内容
            userAction.setActionTime(LocalDateTime.now());
            userAction.setActionContent("还书失败：" + e.getMessage());
            throw e;
        } finally {
            try {
                // 即使主事务回滚，也确保日志写入数据库
                userActionService.createUserAction(userAction);
            } catch (Exception ex) {
                System.err.println("用户行为日志记录失败: " + ex.getMessage());
            }
        }
    }

    private Integer getUserIdFromBorrowRecord(Integer borrowId) {
        BorrowRecord record = borrowingRecordMapper.getBorrowRecordById(borrowId);
        return record != null ? record.getUserId() : -1; // 默认值处理
    }


    // 1. new 通过Id获取借用记录 测试成功
//        BorrowRecord borrowRecordById = borrowingRecordMapper.getBorrowRecordById(new Integer(28));
//        System.out.println("-------->");
//        System.out.println(borrowRecordById.toString());
//        System.out.println("-------->");

    // 2. 测试 更新借阅记录  测试成功
//        BorrowRecord borrowRecord = new BorrowRecord(
//                45,
//                12,
//                9,
//                "2025-10-05 10:20:10",
//                "2025-10-07 10:10:10",
//                0,
//                new BigDecimal(0)
//        );

//        int i = borrowingRecordMapper.updateBorrowRecord(borrowRecord);
//
//        System.out.println("-------->");
//        System.out.println(i);
//        System.out.println("-------->");

    /**
     * 验证用户借书资格
     *
     * @param userId 用户ID
     */
    @LoadSystemSettings // 更新设置
    public void validateBorrowingEligibility(Integer userId) {
        List<BorrowRecord> records = borrowingRecordMapper.selectBorrowRecordsByUserId(userId);

        // 获取未归还的借阅记录
        List<BorrowRecord> activeRecords = records.stream()
                .filter(record -> record.getReturnTime() == null)
                .collect(Collectors.toList());

        // 检查借书限额
        if (activeRecords.size() >= maxBorrowLimit) {
            throw new InvalidRequestException("借书数量已达上限（最多" + maxBorrowLimit + "本）");
        }

        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        // 检查是否有逾期未还图书
        boolean hasOverdue = activeRecords.stream().anyMatch(record -> {
//            LocalDate borrowDate = LocalDate.parse(record.getBorrowTime());
//            LocalDate dueDate = borrowDate.plusDays(borrowPeriodDays);
//            return LocalDate.now().isAfter(dueDate);
            LocalDateTime borrowDateTime = LocalDateTime.parse(record.getBorrowTime(), formatter);

//            System.out.println("debug : borrowDateTime : " + borrowDateTime.toString());

            LocalDateTime dueDateTime = borrowDateTime.plusDays(borrowPeriodDays);
            return LocalDateTime.now().isAfter(dueDateTime);
        });

        if (hasOverdue) {
            throw new InvalidRequestException("存在逾期未还图书，请先归还");
        }
    }

    /**
     * 获取用户借阅记录通过 ID
     */
    @GetMapping("/record/{userId}")
    public List<BorrowRecord> getBorrowRecordsByUserId(@PathVariable Integer userId) {
        return borrowingRecordMapper.getBorrowRecordsByUserId(userId);
    }

    /**
     * 获取所有用户借阅记录
     */
    public List<BorrowRecord> getAllBorrowingRecords() {
        return borrowingRecordMapper.getAllBorrowingRecords();
    }
}



